package cn.yzgy.yzgyoa.ucenter.service.impl;

import cn.yzgy.yzgyoa.common.constant.YzCacheName;
import cn.yzgy.yzgyoa.common.constant.SystemConstant;
import cn.yzgy.yzgyoa.common.crsp.StatusCode;
import cn.yzgy.yzgyoa.common.exception.SystemException;
import cn.yzgy.yzgyoa.common.utils.YzCacheHelper;
import cn.yzgy.yzgyoa.ucenter.dto.MenuItemDto;
import cn.yzgy.yzgyoa.ucenter.entity.SysMenu;
import cn.yzgy.yzgyoa.ucenter.mapper.SysMenuMapper;
import cn.yzgy.yzgyoa.ucenter.service.ISysMenuService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表，用于储存系统中的菜单，权限等信息 服务实现类
 * </p>
 *
 * @author Yqsen
 * @since 2019-08-27
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    private final YzCacheHelper yzCacheHelper;

    public SysMenuServiceImpl(YzCacheHelper yzCacheHelper) {
        this.yzCacheHelper = yzCacheHelper;
    }

    private static final String MID_COLUMN_NAME = "mid";

    /**
     * 遍历菜单
     *
     * @param menus 要遍历的菜单列表
     * @param parentId 从哪一级开始遍历
     * @return 树状菜单结构
     */
    private List<SysMenu> getAllTreeSysMenu(List<SysMenu> menus, Long parentId, Set<String> permissions) {
        List<SysMenu> listOfSysMenu = menus.stream()
                .filter(x -> x.getParentMid().equals(parentId) && hasPermission(x, permissions)).collect(Collectors.toList());
        listOfSysMenu.forEach(x ->  x.setChilds(getAllTreeSysMenu(menus, x.getMid(),permissions)));
        return listOfSysMenu;
    }

    /**
     * 获取Dto形式的菜单
     *
     * @param permissions 权限
     * @return 按Dto格式的菜单
     */
    public List<MenuItemDto> getTreeSysMenuDto(Set<String> permissions) {
        return MenuItemDto.trans(getAllTreeSysMenu(baseMapper.getMenuWithPermName(), 0L, permissions));
    }

//    public List<MenuItemDto>

    /**
     * 判断当前的权限是否能够读取这条菜单
     * @param menu 菜单对象
     * @param permissions 对象集合
     * @return 是否能读取这条菜单
     */
    private boolean hasPermission(SysMenu menu, Set<String> permissions) {
        // 管理员权限
        if(permissions.contains(SystemConstant.ALL_PERMISSIONS_STRING)) {
            return true;
        }
        return permissions.contains(menu.getPermVal());
    }


    @Override
    public List<SysMenu> getUserTreeSysMenu(Set<String> permissions) {
        return getAllTreeSysMenu(baseMapper.getMenuWithPermName(), 0L, permissions);
    }

    /**
     * 删除菜单项
     *
     * @param mId 菜单ID
     * @return 影响条目
     */
    @Override
    public int deleteMenuItem(int mId) {
        final String parentMidColumnName = "parent_mid";
        if (baseMapper.selectCount(new QueryWrapper<SysMenu>().eq(parentMidColumnName, mId)) > 0) {
            throw new SystemException(StatusCode.EXCEPTION, "此菜单存在子菜单，请先删除子菜单再删除父菜单");
        }
        int res = baseMapper.delete(new QueryWrapper<SysMenu>().eq(MID_COLUMN_NAME, mId));
        return yzCacheHelper.autoClearCache(res, YzCacheName.MENU_CACHE_NAME);
    }

    /**
     * 更新菜单项
     * @param menuItemDto 菜单项DTO
     * @return 影响条目
     */
    @Override
    public int updateMenu(MenuItemDto menuItemDto) {
        SysMenu menu = MenuItemDto.getSysMenu(menuItemDto);
        int res = baseMapper.update(
                menu, new UpdateWrapper<SysMenu>().eq(MID_COLUMN_NAME, menu.getMid()));
        return yzCacheHelper.autoClearCache(res, YzCacheName.MENU_CACHE_NAME);
    }

    /**
     * 新增菜单项
     * @param menuItemDto 菜单项DTO
     * @return 插入条数
     */
    @Override
    public int addNewMenu(MenuItemDto menuItemDto) {
        SysMenu menu = MenuItemDto.getSysMenu(menuItemDto);
        int res = baseMapper.insert(menu);
        return yzCacheHelper.autoClearCache(res, YzCacheName.MENU_CACHE_NAME);
    }
}
